#include "PreCompiled.h"
#include "Icons/background.xpm"
#include "MainWindow.h"
#include "Tree.h"
#include "DockWindowManager.h"
#include "CombiView.h"
#include "PropertyView.h"
#include "VIewWindow.h"
#include "Application.h"
#include <QWorkspace>
#include "Command.h"
#if defined(Q_OS_WIN32)
#define slots
#include <private/qmainwindowlayout_p.h>
#include <private/qwidgetresizehandler_p.h>
#endif

struct MainWindowP
{
	QLabel* sizeLabel;
	QLabel* actionLabel;
	QTimer* actionTimer;
	QTimer* activityTimer;
	QTimer* visibleTimer;
    QWorkspace* workspace;
	bool whatsthis;
	QString whatstext;
	QPointer<ViewWindow>activeView;
	QSignalMapper* windowMapper;
};
#if defined(Q_OS_WIN32)
class MainWindowTabBar : public QTabBar
{
public:
	MainWindowTabBar(QWidget *parent) : QTabBar(parent)
	{
		setExpanding(false);
	}
protected:
	bool event(QEvent *e)
	{
		// show the tooltip if tab is too small to fit label
		if (e->type() != QEvent::ToolTip)
			return QTabBar::event(e);
		QSize size = this->size();
		QSize hint = sizeHint();
		if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
			size.transpose();
			hint.transpose();
		}
		if (size.width() < hint.width())
			return QTabBar::event(e);
		e->accept();
		return true;
	}
	void tabInserted (int index)
	{
		// get all dock windows
		QList<QDockWidget*> dw = getMainWindow()->findChildren<QDockWidget*>();
		for (QList<QDockWidget*>::iterator it = dw.begin(); it != dw.end(); ++it) {
			// compare tab text and window title to get the right dock window
			if (this->tabText(index) == (*it)->windowTitle()) {
				QWidget* dock = (*it)->widget();
				if (dock) {
					QIcon icon = dock->windowIcon();
					if (!icon.isNull())
						setTabIcon(index, icon);
				}
				break;
			}
		}
	}
};
#endif





MainWindow* MainWindow::_instance = 0;
MainWindow::MainWindow(QWidget * parent, Qt::WFlags f)
:QMainWindow(parent,f)
{
	d = new struct MainWindowP;
	_instance = this;
	d->activeView = 0;

	QFrame* vbox = new QFrame(this);
	vbox->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
	QVBoxLayout* layout = new QVBoxLayout();
	layout->setMargin(1);
	vbox->setLayout(layout);

	d->workspace = new QWorkspace();
	d->workspace->setScrollBarsEnabled( true );
	QPixmap backgnd((const char**) background);
	d->workspace->setBackground(backgnd);
	layout->addWidget(d->workspace);
	setCentralWidget(vbox);

	d->actionLabel = new QLabel(statusBar());
	d->actionLabel->setMinimumWidth(120);
	d->sizeLabel = new QLabel(tr("Dimension"),statusBar());
	d->sizeLabel->setMinimumWidth(120);
	statusBar()->addWidget(d->actionLabel,0);

	d->actionTimer = new QTimer(this);
	connect(d->actionTimer,SIGNAL(timeout()),d->actionLabel,SLOT(clear()));

	d->activityTimer = new QTimer(this);
	connect(d->activityTimer,SIGNAL(timeout()),this,SLOT(updateActions()));
	d->activityTimer->setSingleShot(true);
	d->activityTimer->start(300);

	d->visibleTimer = new QTimer(this);
	connect(d->visibleTimer,SIGNAL(timeout()),this,SLOT(showMainWindow()));
	d->visibleTimer->setSingleShot(true);

	d->windowMapper = new QSignalMapper(this);

	connect(d->windowMapper,SIGNAL(mapped(QWidget*)),d->workspace,SLOT(setActiveWindow(QWidget*)));

	connect(d->workspace,SIGNAL(windowActivated(QWidget*)),this,SLOT(onWindowActivated(QWidget*)));


   actionLabel = new QLabel(statusBar());
   actionLabel->setMinimumWidth(120);
   sizeLabel = new QLabel(tr(""), statusBar());
   sizeLabel->setMinimumWidth(120);
   statusBar()->addWidget(actionLabel, 0);

   DockWindowManager* pDockMgr = DockWindowManager::instance();

   TreeDockWidget* tree = new TreeDockWidget(this);
   tree->setObjectName(QString::fromAscii(QT_TRANSLATE_NOOP("QDockWidget"," Tree view")));
   tree->setMinimumWidth(210);

   pDockMgr->registerDockWindow("Std_TreeView",tree);

   PropertyDockView* pcPropView = new PropertyDockView(this);
   pcPropView->setObjectName(QT_TRANSLATE_NOOP("QDockWidget","Property view"));
   pcPropView->setMinimumWidth(210);
   pDockMgr->registerDockWindow("Std_ProperytView",pcPropView);

    CombiView* pcCombiView = new CombiView(this);
	pcCombiView->setObjectName(QString::fromAscii(QT_TRANSLATE_NOOP("QDockWidget","Combo View")));
	pcCombiView->setMinimumWidth(150);
	pDockMgr->registerDockWindow("Std_CombiView",pcCombiView);

	//setAcceptDrops(true);
	statusBar()->showMessage(tr("Ready"),2001);
   
}

MainWindow::~MainWindow(void)
{
	delete d;
   _instance = 0;
}
void MainWindow::addWindow(ViewWindow* view)
{
	//QWidget* active = d->workspace->activeWindow();
	d->workspace->addWindow(view);
	setActiveWindow(view);
	int wm = d->workspace->width();
	int hm = d->workspace->height();
	int w = view->width();
	QWidget* p = view->parentWidget();
	if (p) {
		QWidgetResizeHandler* handler = p->findChild<QWidgetResizeHandler*>();
		if (handler) handler->setMovingEnabled(false);
	}
	connect(view, SIGNAL(message(const QString&, int)),
		this, SLOT(showMessage(const QString&, int)));

	connect(this, SIGNAL(windowStateChanged(ViewWindow*)),
		view, SLOT(windowStateChanged(ViewWindow*)));
	view->installEventFilter(this);
    view->showMaximized();


// 	ViewWindow* active_mdi = qobject_cast<ViewWindow*>(active);
// 	d->workspace->setActiveWindow(active);
	d->workspace->setActiveWindow(view);


}
void MainWindow::removeWindow(ViewWindow* view)
{
	disconnect(view, SIGNAL(message(const QString&, int)),
		this, SLOT(showMessage(const QString&, int )));
	disconnect(this, SIGNAL(windowStateChanged(ViewWindow*)),
		view, SLOT(windowStateChanged(ViewWindow*)));
	view->removeEventFilter(this);

	QWidget* foc = this->focusWidget();
	if (foc) {
		QWidget* par = foc->parentWidget();
		while (par) {
			if (par == view) {
				foc->clearFocus();
				break;
			}
			par = par->parentWidget();
		}
	}

	disconnect(view, SIGNAL(destroyed()),
		this, SLOT(onWindowDestroyed()));

	int a = 0;

}

void MainWindow::onWindowDestroyed()
{

}
void MainWindow::keyPressEvent(QKeyEvent *e)
{

}
void MainWindow::updateActions()
{
   static QTime cLastCall;
   if(cLastCall.elapsed() > 250 && isVisible())
   {
	   Application::Instance()->commandMananger().testActive();
	   cLastCall.start();
   }

   d->activityTimer->setSingleShot(true);
   d->activityTimer->start(300);
}
void MainWindow::showMainWindow()
{

}
void MainWindow::onWindowActivated(QWidget* w)
{
  ViewWindow* view = dynamic_cast<ViewWindow*>(w);
  if(!view)
	  return;

  d->activeView = view;

  Application::Instance()->viewActivated(view);

}

void MainWindow::showMessage(const QString & message, int timeout /* = 0 */)
{
	QFontMetrics fm(statusBar()->font());
	QString msg = fm.elidedText(message, Qt::ElideMiddle, this->width()/2);
	this->statusBar()->showMessage(msg, timeout);
}
void MainWindow::loadWindowSettings()
{
   	showMaximized();
}
void MainWindow::setActiveWindow(ViewWindow* view)
{
  d->workspace->setActiveWindow(view);
  d->activeView = view;
  Application::Instance()->viewActivated(view);
}
ViewWindow* MainWindow::activeWindow()const
{
  return d->activeView;
}
MainWindow* MainWindow::getInstance()
{
	return _instance;
}
void MainWindow::closeEvent(QCloseEvent * e)
{
	Application::Instance()->tryClose(e);
	if (e->isAccepted()) {
		// Send close event to all non-modal dialogs
		QList<QDialog*> dialogs = this->findChildren<QDialog*>();
		for (QList<QDialog*>::iterator it = dialogs.begin(); it != dialogs.end(); ++it) {
			(*it)->close();
		}
		QList<ViewWindow*> mdis = this->findChildren<ViewWindow*>();
		// Force to close any remaining (passive) MDI child views
		for (QList<ViewWindow*>::iterator it = mdis.begin(); it != mdis.end(); ++it) {
			(*it)->hide();
			(*it)->deleteLater();
		}
		d->activityTimer->stop();
		//saveWindowSettings();
		//delete d->assistant;
		//d->assistant = 0;

		mainWindowClosed();
		qApp->quit(); // stop the event loop
	}
}
bool MainWindow::eventFilter(QObject * o, QEvent * e)
{ 


	if (o != this) {
		if (e->type() == QEvent::WindowStateChange) {
			// notify all mdi views when the active view receives a show normal, show minimized 
			// or show maximized event 
			ViewWindow * view = qobject_cast<ViewWindow*>(o);
			if (view) { // emit this signal
				Qt::WindowStates oldstate = static_cast<QWindowStateChangeEvent*>(e)->oldState();
				Qt::WindowStates newstate = view->windowState();
				if (oldstate != newstate)
					windowStateChanged(view);
			}
		}

		// We don't want to show the bubble help for the what's this text but want to
		// start the help viewer with the according key word.
		// Thus, we have to observe WhatThis events if called for a widget, use its text and
		// must avoid to make the bubble widget visible.
		if (e->type() == QEvent::WhatsThis) {
			if (!o->isWidgetType())
				return false;
			// clicked on a widget in what's this mode
			QWidget * w = static_cast<QWidget *>(o);
			d->whatstext = w->whatsThis();
		}
		if (e->type() == QEvent::WhatsThisClicked) {
			// if the widget is a top-level window
			if (o->isWidgetType() && qobject_cast<QWidget*>(o)->isWindow()) {
				// re-direct to the widget
				QApplication::sendEvent(this, e);
			}
		}
		// special treatment for menus because they directly call QWhatsThis::showText()
		// whereby we must be informed for which action the help should be shown
		if (o->inherits("QMenu") && QWhatsThis::inWhatsThisMode()) {
			bool whatthis = false;
			if (e->type() == QEvent::KeyPress) {
				QKeyEvent* ke = static_cast<QKeyEvent*>(e);
				if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_F1)
					whatthis = true;
			}
			else if (e->type() == QEvent::MouseButtonRelease)
				whatthis = true;
			else if (e->type() == QEvent::EnterWhatsThisMode)
				whatthis = true;
			if (whatthis) {
				QAction* cur = static_cast<QMenu*>(o)->activeAction();
				if (cur) {
					// get the help text for later usage
					QString s = cur->whatsThis();
					if (s.isEmpty())
						s = static_cast<QMenu*>(o)->whatsThis();
					d->whatstext = s;
				}
			}
		}
		if (o->inherits("QWhatsThat") && e->type() == QEvent::Show) {
			// the bubble help should become visible which we avoid by marking the widget
			// that it is out of range. Instead of, we show the help viewer
			if (!d->whatstext.isEmpty()) {
				QWhatsThisClickedEvent e(d->whatstext);
				QApplication::sendEvent(this, &e);
			}
			static_cast<QWidget *>(o)->setAttribute(Qt::WA_OutsideWSRange);
			return true;
		}
		if (o->inherits("QWhatsThat") && e->type() == QEvent::Hide) {
			// leave what's this mode
			if (d->whatsthis) {
				d->whatsthis = false;
				d->whatstext.clear();
				qApp->removeEventFilter(this);
			}
		}
	}

	return QMainWindow::eventFilter(o, e);
}

#include "moc_mainwindow.cpp"
